"""
行为检测模块 - 商业级行为识别
检测用户正在做什么：聊天、走路、转身、睡觉、工作等
"""

import numpy as np
import cv2
from typing import Dict, List, Optional, Tuple
import time
from collections import deque
import math

class BehaviorDetector:
    """行为检测器 - 识别用户的实际行为"""
    
    def __init__(self, history_size: int = 30):
        """
        初始化行为检测器
        
        Args:
            history_size: 历史记录大小，用于行为分析
        """
        self.history_size = history_size
        
        # 行为历史记录
        self.pose_history = deque(maxlen=history_size)
        self.landmark_history = deque(maxlen=history_size)
        self.movement_history = deque(maxlen=history_size)
        
        # 行为状态
        self.current_behavior = "unknown"
        self.behavior_confidence = 0.0
        self.behavior_duration = 0
        self.last_behavior_change = time.time()
        
        # 行为平滑处理
        self.behavior_history = deque(maxlen=15)  # 行为历史记录
        self.min_behavior_duration = 3.0  # 最小行为持续时间（秒）
        self.behavior_change_threshold = 0.7  # 行为变化阈值
        
        # 状态记忆机制
        self.work_detection_count = 0  # 连续工作检测次数
        self.sleep_detection_count = 0  # 连续睡觉检测次数
        self.required_work_detections = 5  # 需要连续5次检测为工作
        self.required_sleep_detections = 8  # 需要连续8次检测为睡觉
        self.still_detection_count = 0  # 静止检测次数
        self.required_still_detections = 30  # 需要连续30次检测为静止（约15秒）
        self.eye_closed_count = 0  # 眼睛闭合检测次数
        self.required_eye_closed = 20  # 需要连续20次检测为眼睛闭合
        
        # 运动分析参数
        self.movement_threshold = 0.02  # 运动阈值
        self.turn_threshold = 30  # 转身角度阈值（度）
        self.still_threshold = 0.01  # 静止阈值
        
        # 注意力分析参数
        self.attention_threshold = 0.7  # 注意力阈值
        self.chat_threshold = 0.3  # 聊天阈值（头部转动频率）

        # 吃东西检测状态
        self.eating_candidate_start_time: Optional[float] = None
        self.eating_active: bool = False
        
    def add_pose(self, landmarks, pose_result: Dict) -> Dict:
        """
        添加姿态数据并分析行为
        
        Args:
            landmarks: 关键点坐标
            pose_result: 姿态分类结果
            
        Returns:
            行为检测结果
        """
        if landmarks is None:
            return self._get_unknown_behavior()
        
        # 记录历史数据
        self.pose_history.append(pose_result)
        
        # 处理landmarks对象
        try:
            # 如果是MediaPipe的landmarks对象，直接存储
            if hasattr(landmarks, 'landmark'):
                self.landmark_history.append(landmarks)
            elif isinstance(landmarks, np.ndarray) and landmarks.ndim > 0:
                self.landmark_history.append(landmarks.copy())
            else:
                # 其他情况跳过
                pass
        except:
            # 如果转换失败，跳过这次记录
            pass
        
        # 分析行为
        behavior_result = self._analyze_behavior()
        
        return behavior_result
    
    def _analyze_behavior(self) -> Dict:
        """分析当前行为"""
        # 安全检查landmark_history
        try:
            if len(self.landmark_history) < 3:  # 减少到3帧就开始工作
                return self._get_unknown_behavior()
        except:
            return self._get_unknown_behavior()
        
        # 安全获取当前和历史的姿态数据
        try:
            current_landmarks = self.landmark_history[-1] if len(self.landmark_history) > 0 else None
            current_pose = self.pose_history[-1] if len(self.pose_history) > 0 else {'pose': 'unknown'}
            
            if current_landmarks is None:
                return self._get_unknown_behavior()
        except:
            return self._get_unknown_behavior()
        
        # 分析各种行为
        behaviors = {
            'sleeping': self._detect_sleeping(current_landmarks, current_pose),
            'walking': self._detect_walking(current_landmarks),
            'turning': self._detect_turning(current_landmarks),
            'chatting': self._detect_chatting(current_landmarks),
            'working': self._detect_working(current_landmarks, current_pose),
            'standing': self._detect_standing(current_landmarks, current_pose),
            'sitting': self._detect_sitting(current_landmarks, current_pose),
            'raising_left': self._detect_raising_hand_side(current_landmarks, 'left'),
            'raising_right': self._detect_raising_hand_side(current_landmarks, 'right'),
            'raising_both': self._detect_raising_both(current_landmarks),
            'eating': self._detect_eating(current_landmarks),
            # 新增行为（精简掉跪拜以降低算力）
            'extend_left': self._detect_extending_hand_side(current_landmarks, 'left'),
            'extend_right': self._detect_extending_hand_side(current_landmarks, 'right'),
            'extend_both': self._detect_extending_both(current_landmarks),
            'extend_both_horizontal': self._detect_extending_both_horizontal(current_landmarks),
            'jumping_knees_up': self._detect_jumping_knees_up(current_landmarks)
        }
        
        # 找到最可能的行为
        best_behavior = max(behaviors.items(), key=lambda x: x[1])
        
        # 添加行为到历史记录
        self.behavior_history.append(best_behavior[0])
        
        # 应用新的状态判断逻辑
        detected_behavior = best_behavior[0]  # 添加这行定义变量
        final_behavior = self._determine_final_behavior(detected_behavior, best_behavior[1], behaviors)
        
        # 更新行为状态
        if final_behavior != self.current_behavior:
            # 检查是否满足最小持续时间要求
            current_duration = time.time() - self.last_behavior_change
            if current_duration >= self.min_behavior_duration or self.current_behavior == "unknown":
                self.current_behavior = final_behavior
                self.behavior_confidence = best_behavior[1]
                self.behavior_duration = 0
                self.last_behavior_change = time.time()
            else:
                # 保持当前行为，但更新置信度
                self.behavior_confidence = best_behavior[1]
                self.behavior_duration = current_duration
        else:
            self.behavior_confidence = best_behavior[1]
            self.behavior_duration = time.time() - self.last_behavior_change
        
        return {
            'behavior': self.current_behavior,
            'confidence': self.behavior_confidence,
            'duration': self.behavior_duration,
            'chinese_name': self._get_behavior_chinese_name(self.current_behavior),
            'all_behaviors': behaviors,
            'debug_info': {
                'work_count': self.work_detection_count,
                'sleep_count': self.sleep_detection_count,
                'still_count': self.still_detection_count,
                'eye_closed_count': self.eye_closed_count,
                'detected_behavior': detected_behavior,
                'is_still': self._check_still_condition(behaviors),
                'eyes_closed': self._detect_eye_closed(self.landmark_history[-1] if self.landmark_history else None)
            }
        }
    
    def _determine_final_behavior(self, detected_behavior: str, confidence: float, all_behaviors: Dict) -> str:
        """确定最终行为，使用状态记忆机制避免误判"""
        
        # 检查是否检测到静止状态
        is_still = self._check_still_condition(all_behaviors)
        
        # 工作状态判断
        if detected_behavior == 'working' and confidence > 0.6:
            self.work_detection_count += 1
            self.sleep_detection_count = 0  # 重置睡觉计数
            self.still_detection_count = 0  # 重置静止计数
            
            # 需要连续多次检测为工作才判定
            if self.work_detection_count >= self.required_work_detections:
                return 'working'
            else:
                # 保持当前状态，除非当前是未知状态
                return self.current_behavior if self.current_behavior != 'unknown' else 'working'
        
        # 睡觉状态判断（需要更严格的条件）
        elif detected_behavior == 'sleeping' and confidence > 0.7:
            self.sleep_detection_count += 1
            self.work_detection_count = 0  # 重置工作计数
            
            # 检查眼睛是否闭合
            current_landmarks = self.landmark_history[-1] if self.landmark_history else None
            eyes_closed = self._detect_eye_closed(current_landmarks)
            
            if eyes_closed:
                self.eye_closed_count += 1
            else:
                self.eye_closed_count = 0
            
            # 需要连续多次检测为睡觉，且必须是静止状态，且眼睛闭合
            if (self.sleep_detection_count >= self.required_sleep_detections and 
                is_still and 
                self.eye_closed_count >= self.required_eye_closed and
                all_behaviors.get('sleeping', 0) > 0.8):
                return 'sleeping'
            else:
                # 保持当前状态，避免误判
                return self.current_behavior if self.current_behavior != 'unknown' else 'unknown'
        
        # 其他行为（聊天、走路、转身等）
        elif detected_behavior in ['chatting', 'walking', 'turning', 'standing', 'sitting', 'raising_left', 'raising_right', 'raising_both', 'eating',
                                   'extend_left', 'extend_right', 'extend_both', 'extend_both_horizontal', 'jumping_knees_up']:
            # 重置工作、睡觉、静止计数
            self.work_detection_count = 0
            self.sleep_detection_count = 0
            self.still_detection_count = 0
            
            # 这些行为可以立即切换
            if confidence > 0.6:
                return detected_behavior
            else:
                return self.current_behavior if self.current_behavior != 'unknown' else detected_behavior
        
        # 未知状态
        else:
            # 重置所有计数
            self.work_detection_count = 0
            self.sleep_detection_count = 0
            self.still_detection_count = 0
            return 'unknown'
    
    def _check_still_condition(self, all_behaviors: Dict) -> bool:
        """检查是否处于静止状态"""
        # 计算整体运动强度
        overall_movement = self._calculate_overall_movement()
        
        # 如果运动强度很低，认为是静止
        if overall_movement < self.still_threshold:
            self.still_detection_count += 1
        else:
            self.still_detection_count = 0
        
        # 需要连续多次检测为静止
        return self.still_detection_count >= self.required_still_detections
    
    def _smooth_behavior_change(self, new_behavior: str, confidence: float) -> str:
        """平滑行为变化，避免频繁切换"""
        # 如果历史记录不足，直接返回新行为
        if len(self.behavior_history) < 5:
            return new_behavior
        
        # 统计最近的行为
        recent_behaviors = list(self.behavior_history)[-5:]  # 最近5次检测
        behavior_counts = {}
        for behavior in recent_behaviors:
            behavior_counts[behavior] = behavior_counts.get(behavior, 0) + 1
        
        # 找到最频繁的行为
        most_frequent_behavior = max(behavior_counts.items(), key=lambda x: x[1])
        
        # 如果新行为在最近5次中出现次数足够多，或者置信度很高，则采用新行为
        if (behavior_counts.get(new_behavior, 0) >= 3 or 
            confidence >= self.behavior_change_threshold):
            return new_behavior
        else:
            # 否则保持最频繁的行为
            return most_frequent_behavior[0]
    
    def _detect_sleeping(self, landmarks, pose_result: Dict) -> float:
        """检测睡觉行为 - 更严格的判断条件"""
        if pose_result.get('pose') != 'lying_down':
            return 0.0
        
        # 检查头部是否向下
        head_angle = self._calculate_head_angle(landmarks)
        if head_angle < -30:  # 头部向下倾斜
            head_score = 0.9
        elif head_angle < -15:  # 头部稍微向下
            head_score = 0.7
        else:
            head_score = 0.3
        
        # 检查身体是否平躺
        body_angle = self._calculate_body_angle(landmarks)
        if abs(body_angle) < 15:  # 身体基本水平
            body_score = 0.9
        elif abs(body_angle) < 30:  # 身体稍微倾斜
            body_score = 0.6
        else:
            body_score = 0.2
        
        # 检查眼睛是否闭合
        eyes_closed = self._detect_eye_closed(landmarks)
        eye_score = 0.9 if eyes_closed else 0.2
        
        # 检查是否长时间静止（睡觉时应该很少动）
        is_still = self._check_still_condition({'sleeping': 0.5})  # 传入一个默认值
        still_score = 0.9 if is_still else 0.3
        
        # 综合评分，需要多个条件都满足
        final_score = (head_score * 0.3 + body_score * 0.3 + eye_score * 0.3 + still_score * 0.1)
        
        # 只有综合评分很高才认为是睡觉
        return final_score if final_score > 0.7 else 0.0
    
    def _detect_walking(self, landmarks) -> float:
        """检测走路行为"""
        # 安全检查landmark_history
        try:
            if len(self.landmark_history) < 10:
                return 0.0
        except:
            return 0.0
        
        # 计算腿部运动
        leg_movement = self._calculate_leg_movement()
        
        # 计算整体运动
        overall_movement = self._calculate_overall_movement()
        
        # 走路特征：腿部有规律运动，整体有前进趋势
        if leg_movement > self.movement_threshold and overall_movement > self.movement_threshold * 0.5:
            return min(0.9, leg_movement * 10)
        
        return 0.0
    
    def _detect_turning(self, landmarks) -> float:
        """检测转身行为"""
        # 安全检查landmark_history
        try:
            if len(self.landmark_history) < 5:
                return 0.0
        except:
            return 0.0
        
        # 计算头部转动角度
        head_turn = self._calculate_head_turn()
        
        # 计算身体转动角度
        body_turn = self._calculate_body_turn()
        
        # 转身特征：头部或身体有明显转动
        max_turn = max(abs(head_turn), abs(body_turn))
        
        if max_turn > self.turn_threshold:
            return min(0.9, max_turn / 90.0)
        
        return 0.0
    
    def _detect_chatting(self, landmarks) -> float:
        """检测聊天行为"""
        # 安全检查landmark_history
        try:
            if len(self.landmark_history) < 10:
                return 0.0
        except:
            return 0.0
        
        # 计算头部转动频率
        head_turn_frequency = self._calculate_head_turn_frequency()
        
        # 计算手部活动
        hand_activity = self._calculate_hand_activity()
        
        # 聊天特征：头部频繁转动，手部有活动
        chat_score = 0.0
        
        if head_turn_frequency > self.chat_threshold:
            chat_score += 0.6
        
        if hand_activity > 0.3:
            chat_score += 0.4
        
        return min(0.9, chat_score)

    def _detect_eating(self, landmarks) -> float:
        """检测吃东西：手掌靠近嘴部，且手部轻微运动，持续超过2秒"""
        try:
            if landmarks is None or not hasattr(landmarks, 'landmark'):
                # 重置状态
                self.eating_candidate_start_time = None
                self.eating_active = False
                return 0.0

            # 口部/鼻子位置（优先用口角9、10，否则用鼻子0）
            lm = landmarks.landmark
            has_mouth = len(lm) > 10
            if has_mouth:
                mouth_x = (lm[9].x + lm[10].x) / 2.0
                mouth_y = (lm[9].y + lm[10].y) / 2.0
            else:
                mouth_x = lm[0].x
                mouth_y = lm[0].y

            # 近似手掌位置：使用手腕(15/16)、食指(19/20)、拇指(21/22)的平均
            def hand_proxy(side: str) -> Optional[Tuple[float, float]]:
                try:
                    if side == 'left':
                        pts = []
                        if len(lm) > 15: pts.append((lm[15].x, lm[15].y))
                        if len(lm) > 19: pts.append((lm[19].x, lm[19].y))
                        if len(lm) > 21: pts.append((lm[21].x, lm[21].y))
                    else:
                        pts = []
                        if len(lm) > 16: pts.append((lm[16].x, lm[16].y))
                        if len(lm) > 20: pts.append((lm[20].x, lm[20].y))
                        if len(lm) > 22: pts.append((lm[22].x, lm[22].y))
                    if not pts:
                        return None
                    xs = [p[0] for p in pts]
                    ys = [p[1] for p in pts]
                    return (float(np.mean(xs)), float(np.mean(ys)))
                except Exception:
                    return None

            # 依据肩宽自适应阈值（更鲁棒）
            try:
                if len(lm) > 12:
                    shoulder_dist = math.sqrt((lm[12].x - lm[11].x)**2 + (lm[12].y - lm[11].y)**2)
                else:
                    shoulder_dist = 0.25
            except Exception:
                shoulder_dist = 0.25
            near_thr = max(0.07, min(0.13, 0.45 * shoulder_dist))

            near = False
            min_dist = 1.0
            for side in ('left', 'right'):
                hp = hand_proxy(side)
                if hp is None:
                    continue
                d = math.sqrt((hp[0] - mouth_x)**2 + (hp[1] - mouth_y)**2)
                min_dist = min(min_dist, d)
                if d < near_thr:
                    near = True

            # 手部轻微移动（在最近窗口内的均值位移处于小幅范围）
            motion = self._wrist_motion_magnitude(window=12)
            slight_motion = 0.001 <= motion <= 0.05

            now = time.time()
            if near and slight_motion:
                if self.eating_candidate_start_time is None:
                    self.eating_candidate_start_time = now
                    self.eating_active = False
                else:
                    if now - self.eating_candidate_start_time >= 2.0:
                        self.eating_active = True
            else:
                self.eating_candidate_start_time = None
                self.eating_active = False

            # 打分：满足条件且超过2秒给出较高分
            if self.eating_active:
                # 分数随靠近程度和轻微运动强度上升，并考虑肘部弯曲
                proximity_score = max(0.0, min(1.0, (near_thr - min_dist) / max(1e-6, near_thr)))
                motion_score = max(0.0, min(1.0, (0.05 - abs(motion - 0.01)) / 0.05))

                # 肘角弯曲度（吃东西时通常手臂弯曲）
                elbow_bonus = 0.0
                try:
                    def elbow_angle(shoulder, elbow, wrist):
                        p_sh = np.array([shoulder.x, shoulder.y]); p_el = np.array([elbow.x, elbow.y]); p_wr = np.array([wrist.x, wrist.y])
                        v1 = p_sh - p_el; v2 = p_wr - p_el
                        denom = (np.linalg.norm(v1) * np.linalg.norm(v2))
                        if denom <= 1e-6:
                            return 180.0
                        return math.degrees(math.acos(np.clip(np.dot(v1, v2) / denom, -1.0, 1.0)))
                    if len(lm) > 16:
                        la = elbow_angle(lm[11], lm[13], lm[15])
                        ra = elbow_angle(lm[12], lm[14], lm[16])
                        bent = 0
                        if la < 160: bent += 1
                        if ra < 160: bent += 1
                        elbow_bonus = 0.1 * bent  # 0, 0.1, 0.2
                except Exception:
                    elbow_bonus = 0.0

                return min(0.98, 0.55 + 0.3 * proximity_score + 0.15 * motion_score + elbow_bonus)
            return 0.0
        except Exception:
            return 0.0

    def _detect_jumping_knees_up(self, landmarks) -> float:
        """检测跳跃/双膝上抬：两膝上移且高于腹部（髋部）水平，伴随向上运动"""
        try:
            if landmarks is None or not hasattr(landmarks, 'landmark'):
                return 0.0
            if len(self.landmark_history) < 5:
                return 0.0

            lm = landmarks.landmark
            if len(lm) < 29:
                return 0.0

            lhip = lm[23]; rhip = lm[24]
            lknee = lm[25]; rknee = lm[26]
            lankle = lm[27]; rankle = lm[28]

            hip_level = (lhip.y + rhip.y) / 2.0

            # 位置条件：双膝高于髋部一定幅度
            knee_above_left = 1.0 if lknee.y < hip_level - 0.02 else 0.0
            knee_above_right = 1.0 if rknee.y < hip_level - 0.02 else 0.0
            pos_score = 0.5 * (knee_above_left + knee_above_right)  # 0, 0.5, 1.0

            # 速度条件：最近几帧膝盖显著向上移动（y 减小）
            def avg_delta_y(idx: int, window: int = 4) -> float:
                cnt = 0; acc = 0.0
                for i in range(1, min(window, len(self.landmark_history))):
                    a = self.landmark_history[-i-1]
                    b = self.landmark_history[-i]
                    if hasattr(a, 'landmark') and hasattr(b, 'landmark') and len(a.landmark) > idx and len(b.landmark) > idx:
                        acc += (a.landmark[idx].y - b.landmark[idx].y)  # 正值表示向上
                        cnt += 1
                return acc / cnt if cnt > 0 else 0.0

            up_l = avg_delta_y(25)
            up_r = avg_delta_y(26)
            vel_score = 0.0
            for v in (up_l, up_r):
                if v > 0.03:
                    vel_score += 0.5
                elif v > 0.02:
                    vel_score += 0.3

            # 脚踝也上移可加分（整体腾空趋势）
            up_la = avg_delta_y(27)
            up_ra = avg_delta_y(28)
            ankle_bonus = 0.0
            if up_la > 0.02 and up_ra > 0.02:
                ankle_bonus = 0.1

            final = 0.6 * pos_score + 0.3 * min(1.0, vel_score) + 0.1 * ankle_bonus
            return final if final > 0.6 else 0.0
        except Exception:
            return 0.0

    def _wrist_motion_magnitude(self, window: int = 15) -> float:
        """计算最近window帧手腕平均位移（归一化），表示轻微运动强度"""
        try:
            n = len(self.landmark_history)
            if n < 2:
                return 0.0
            start = max(0, n - window)
            disps = []
            for i in range(start, n - 1):
                a = self.landmark_history[i]
                b = self.landmark_history[i + 1]
                if not (hasattr(a, 'landmark') and hasattr(b, 'landmark')):
                    continue
                if len(a.landmark) <= 16 or len(b.landmark) <= 16:
                    continue
                awl = a.landmark[15]; awr = a.landmark[16]
                bwl = b.landmark[15]; bwr = b.landmark[16]
                dl = math.sqrt((bwl.x - awl.x)**2 + (bwl.y - awl.y)**2)
                dr = math.sqrt((bwr.x - awr.x)**2 + (bwr.y - awr.y)**2)
                disps.append((dl + dr) / 2.0)
            return float(np.mean(disps)) if disps else 0.0
        except Exception:
            return 0.0

    def _detect_raising_hand_side(self, landmarks, side: str) -> float:
        """检测单侧举手：手腕高于头部（而非仅高于肩膀）"""
        try:
            if landmarks is None or not hasattr(landmarks, 'landmark'):
                return 0.0
            if len(landmarks.landmark) < 17:
                return 0.0

            lm = landmarks.landmark
            try:
                head_level = min(lm[2].y, lm[5].y)
            except Exception:
                head_level = lm[0].y

            if side == 'left':
                wrist = lm[15]
                other_wrist = lm[16]
            else:
                wrist = lm[16]
                other_wrist = lm[15]

            raised = wrist.y < head_level - 0.02
            gap = max(0.0, (head_level - wrist.y))
            gap_score = min(1.0, gap * 6.0)

            other_raised = other_wrist.y < head_level - 0.02
            penalty = 0.4 if other_raised else 0.0

            score = (1.0 if raised else 0.0) * 0.7 + gap_score * 0.3
            score = max(0.0, score - penalty)
            return score
        except Exception:
            return 0.0

    def _detect_raising_both(self, landmarks) -> float:
        """检测双手举手：双腕均高于头部"""
        try:
            if landmarks is None or not hasattr(landmarks, 'landmark'):
                return 0.0
            if len(landmarks.landmark) < 17:
                return 0.0

            lm = landmarks.landmark
            try:
                head_level = min(lm[2].y, lm[5].y)
            except Exception:
                head_level = lm[0].y

            lw = lm[15]
            rw = lm[16]

            left_ok = lw.y < head_level - 0.02
            right_ok = rw.y < head_level - 0.02

            if not (left_ok and right_ok):
                return 0.0

            # 举得越高分数越高（取两侧相对头部的平均间隙）
            left_gap = max(0.0, (head_level - lw.y))
            right_gap = max(0.0, (head_level - rw.y))
            avg_gap = (left_gap + right_gap) / 2.0
            return min(1.0, avg_gap * 3.0)
        except Exception:
            return 0.0

    def _detect_kneeling_worship(self, landmarks, pose_result: Dict) -> float:
        """检测跪拜：需满足更严格条件
        - 双膝明显弯曲（跪姿特征）
        - 身体前倾角度明显（仅低头不算）
        - 双手在胸前靠拢且不高于头部（合十/胸前）
        仅跪下或仅低头不会触发跪拜。
        """
        try:
            if landmarks is None or not hasattr(landmarks, 'landmark'):
                return 0.0
            if len(landmarks.landmark) < 29:
                return 0.0

            lm = landmarks.landmark
            # 关节点
            lhip = lm[23]; lknee = lm[25]; lankle = lm[27]
            rhip = lm[24]; rknee = lm[26]; rankle = lm[28]

            # 手在胸前靠拢判定（与 _detect_praying 一致但容差略宽松）
            try:
                ls = lm[11]; rs = lm[12]
                lw = lm[15]; rw = lm[16]
                head_level = min(lm[2].y, lm[5].y) if len(lm) > 5 else lm[0].y
                wrists_dist = math.sqrt((lw.x - rw.x)**2 + (lw.y - rw.y)**2)
                close_wrists = wrists_dist < 0.07
                shoulder_center_y = (ls.y + rs.y) / 2.0
                chest_y_min = shoulder_center_y + 0.02
                chest_y_max = shoulder_center_y + 0.22
                lw_in_chest = chest_y_min <= lw.y <= chest_y_max
                rw_in_chest = chest_y_min <= rw.y <= chest_y_max
                not_above_head = lw.y > head_level and rw.y > head_level
                hands_chest_ok = close_wrists and lw_in_chest and rw_in_chest and not_above_head
            except Exception:
                hands_chest_ok = False

            if not hands_chest_ok:
                # 没有合十胸前，不判为跪拜
                return 0.0

            # 身体前倾角度（要求更大角度）
            body_lean = self._calculate_body_lean(landmarks)
            if body_lean < 25.0:
                # 前倾不够大，不判为跪拜
                return 0.0

            # 膝盖角度
            def angle_at_knee(hip, knee, ankle):
                p1 = np.array([hip.x, hip.y])
                p2 = np.array([knee.x, knee.y])
                p3 = np.array([ankle.x, ankle.y])
                v1 = p1 - p2
                v2 = p3 - p2
                denom = (np.linalg.norm(v1) * np.linalg.norm(v2))
                if denom <= 1e-6:
                    return 180.0
                cosang = np.clip(np.dot(v1, v2) / denom, -1.0, 1.0)
                return math.degrees(math.acos(cosang))

            lk_ang = angle_at_knee(lhip, lknee, lankle)
            rk_ang = angle_at_knee(rhip, rknee, rankle)

            # 两膝均需明显弯曲（更严格，阈值放宽到 <85 也给分，但最好 <70）
            knee_score = 0.0
            left_knee_ok = False; right_knee_ok = False
            for ang, side in [(lk_ang, 'L'), (rk_ang, 'R')]:
                if ang < 70:
                    knee_score += 0.6
                    if side == 'L': left_knee_ok = True
                    else: right_knee_ok = True
                elif ang < 85:
                    knee_score += 0.4
                    if side == 'L': left_knee_ok = True
                    else: right_knee_ok = True
            knee_score = min(1.0, knee_score)

            if not (left_knee_ok and right_knee_ok):
                return 0.0

            # 脚踝位于膝盖后方（y 更大）
            ankle_behind_left = 1.0 if lankle.y > lknee.y + 0.03 else 0.0
            ankle_behind_right = 1.0 if rankle.y > rknee.y + 0.03 else 0.0
            ankle_score = (ankle_behind_left + ankle_behind_right) / 2.0

            # 髋部较低（接近或低于膝盖）
            hip_low_left = 1.0 if lhip.y > lknee.y - 0.02 else 0.0
            hip_low_right = 1.0 if rhip.y > rknee.y - 0.02 else 0.0
            hip_low_score = (hip_low_left + hip_low_right) / 2.0

            # 组合评分：膝盖形态为主，配合脚踝/髋部，手势与前倾已作硬性门槛
            final = 0.6 * knee_score + 0.2 * ankle_score + 0.2 * hip_low_score
            return final if final > 0.65 else 0.0
        except Exception:
            return 0.0

    def _detect_extending_hand_side(self, landmarks, side: str) -> float:
        """检测单侧伸手：手臂基本伸直且与地面近乎平行（水平）"""
        try:
            if landmarks is None or not hasattr(landmarks, 'landmark'):
                return 0.0
            if len(landmarks.landmark) < 17:
                return 0.0

            if side == 'left':
                shoulder = landmarks.landmark[11]
                elbow = landmarks.landmark[13]
                wrist = landmarks.landmark[15]
            else:
                shoulder = landmarks.landmark[12]
                elbow = landmarks.landmark[14]
                wrist = landmarks.landmark[16]

            # 肘角接近 180 度视为伸直
            p_sh = np.array([shoulder.x, shoulder.y])
            p_el = np.array([elbow.x, elbow.y])
            p_wr = np.array([wrist.x, wrist.y])
            v1 = p_sh - p_el
            v2 = p_wr - p_el
            denom = (np.linalg.norm(v1) * np.linalg.norm(v2))
            if denom <= 1e-6:
                return 0.0
            ang = math.degrees(math.acos(np.clip(np.dot(v1, v2) / denom, -1.0, 1.0)))
            if ang <= 165:
                return 0.0

            # 水平程度：手腕与肩膀的 y 差需很小（水平）
            if abs(wrist.y - shoulder.y) >= 0.06:
                return 0.0

            # 距离要求：伸出一定长度
            dist = float(np.linalg.norm(p_wr - p_sh))
            if dist <= 0.18:
                return 0.0

            # 满足水平且伸直，按距离映射分数
            dist_score = 0.6 if dist > 0.22 else 0.8 if dist > 0.26 else 0.7
            return min(1.0, dist_score)
        except Exception:
            return 0.0

    def _detect_extending_both(self, landmarks) -> float:
        """检测双手伸直（不限定方向）"""
        try:
            left = self._detect_extending_hand_side(landmarks, 'left')
            right = self._detect_extending_hand_side(landmarks, 'right')
            if left == 0.0 or right == 0.0:
                return 0.0
            return min(1.0, (left + right) / 2.0)
        except Exception:
            return 0.0

    def _detect_extending_both_horizontal(self, landmarks) -> float:
        """检测双手平伸（水平方向，双腕与双肩近同高，且手臂伸直）"""
        try:
            if landmarks is None or not hasattr(landmarks, 'landmark'):
                return 0.0
            if len(landmarks.landmark) < 17:
                return 0.0

            ls = landmarks.landmark[11]; le = landmarks.landmark[13]; lw = landmarks.landmark[15]
            rs = landmarks.landmark[12]; re = landmarks.landmark[14]; rw = landmarks.landmark[16]

            # 肘角
            def elbow_angle(sh, el, wr):
                p_sh = np.array([sh.x, sh.y])
                p_el = np.array([el.x, el.y])
                p_wr = np.array([wr.x, wr.y])
                v1 = p_sh - p_el
                v2 = p_wr - p_el
                denom = (np.linalg.norm(v1) * np.linalg.norm(v2))
                if denom <= 1e-6:
                    return 180.0
                return math.degrees(math.acos(np.clip(np.dot(v1, v2) / denom, -1.0, 1.0)))

            la = elbow_angle(ls, le, lw)
            ra = elbow_angle(rs, re, rw)
            straight = (1.0 if la > 165 else 0.0) + (1.0 if ra > 165 else 0.0)
            straight_score = 0.5 * straight  # 0, 0.5, 1.0

            # 同高性
            left_level = 1.0 if abs(lw.y - ls.y) < 0.06 else 0.0
            right_level = 1.0 if abs(rw.y - rs.y) < 0.06 else 0.0
            level_score = 0.5 * (left_level + right_level)

            # 距离肩膀的水平延展
            left_dist = abs(lw.x - ls.x)
            right_dist = abs(rw.x - rs.x)
            dist_score = 0.0
            if left_dist > 0.22:
                dist_score += 0.5
            if right_dist > 0.22:
                dist_score += 0.5

            final = 0.5 * straight_score + 0.3 * level_score + 0.2 * dist_score
            return final if final > 0.6 else 0.0
        except Exception:
            return 0.0

    def _detect_praying(self, landmarks) -> float:
        """检测拜佛：双手在胸前靠拢（两腕距离小），位置在胸前，头朝前"""
        try:
            if landmarks is None or not hasattr(landmarks, 'landmark'):
                return 0.0
            if len(landmarks.landmark) < 17:
                return 0.0

            lm = landmarks.landmark
            ls = lm[11]; rs = lm[12]
            lw = lm[15]; rw = lm[16]

            # 手靠拢
            wrists_dist = math.sqrt((lw.x - rw.x)**2 + (lw.y - rw.y)**2)
            close_wrists = wrists_dist < 0.06

            # 胸前区域（肩中心下方一定范围）
            shoulder_center_y = (ls.y + rs.y) / 2.0
            chest_y_min = shoulder_center_y + 0.02
            chest_y_max = shoulder_center_y + 0.18
            lw_in_chest = chest_y_min <= lw.y <= chest_y_max
            rw_in_chest = chest_y_min <= rw.y <= chest_y_max

            # 不应高于头（避免被判为举手）
            try:
                head_level = min(lm[2].y, lm[5].y)
            except Exception:
                head_level = lm[0].y
            not_above_head = lw.y > head_level and rw.y > head_level

            # 头朝前
            head_forward = self._calculate_head_orientation_score(landmarks) > 0.6

            if not (close_wrists and lw_in_chest and rw_in_chest and not_above_head and head_forward):
                return 0.0

            # 分数：根据手靠拢程度与胸前程度给分
            closeness_score = max(0.0, min(1.0, (0.06 - wrists_dist) / 0.06))
            chest_score = 0.5 if lw_in_chest and rw_in_chest else 0.0
            return min(0.95, 0.5 + 0.4 * closeness_score + 0.1 * chest_score)
        except Exception:
            return 0.0
    
    def _detect_working(self, landmarks, pose_result: Dict) -> float:
        """检测工作行为"""
        pose = pose_result.get('pose', 'unknown')
        
        # 工作姿态：坐着或站着，身体前倾
        if pose in ['sitting', 'standing']:
            # 检查身体前倾角度
            body_lean = self._calculate_body_lean(landmarks)
            
            # 检查手部位置（可能在键盘或桌面上）
            hand_position = self._calculate_hand_position(landmarks)
            
            # 检查手部稳定性（工作时手部通常有小幅稳定动作）
            hand_stability = self._calculate_hand_stability()
            
            # 检查头部朝向（通常朝向工作区域）
            head_orientation = self._calculate_head_orientation_score(landmarks)
            
            work_score = 0.5  # 基础分数
            
            if body_lean > 10:
                work_score += 0.2
            elif body_lean > 5:
                work_score += 0.1
            
            if hand_position > 0.7:
                work_score += 0.2
            elif hand_position > 0.5:
                work_score += 0.1
            
            if 0.3 < hand_stability < 0.7:  # 适中的手部稳定性
                work_score += 0.2
            
            if head_orientation > 0.6:
                work_score += 0.1
            
            return min(0.95, work_score)
        
        return 0.0
    
    def _detect_using_phone(self, landmarks: np.ndarray) -> float:
        """检测使用手机行为"""
        # 安全检查landmarks是否有效且有足够的数据
        try:
            if isinstance(landmarks, np.ndarray) and landmarks.shape[0] < 33:
                return 0.0
            elif hasattr(landmarks, '__len__') and len(landmarks) < 33:
                return 0.0
        except:
            return 0.0
        
        # 获取关键点
        left_hand = landmarks[15]  # 左手腕
        right_hand = landmarks[16]  # 右手腕
        nose = landmarks[0]
        left_eye = landmarks[2]
        right_eye = landmarks[5]
        
        # 检测手部是否靠近头部
        eye_avg = (left_eye + right_eye) / 2
        
        left_hand_to_face = np.linalg.norm(left_hand[:2] - eye_avg[:2])
        right_hand_to_face = np.linalg.norm(right_hand[:2] - eye_avg[:2])
        
        # 检测头部是否向下倾斜（看手机）
        head_angle = self._calculate_head_angle(landmarks)
        
        score = 0.0
        
        # 手部靠近面部
        if left_hand_to_face < 0.15 or right_hand_to_face < 0.15:
            score += 0.5
        
        # 头部向下倾斜
        if head_angle > 15:  # 假设大于15度表示向下看
            score += 0.4
        
        # 检查手部是否在合适的高度
        hand_y = min(left_hand[1], right_hand[1])
        face_y = eye_avg[1]
        
        if 0.8 * face_y < hand_y < 1.2 * face_y:  # 手部在面部附近
            score += 0.2
        
        return min(0.95, score)
    
    def _detect_eating_drinking(self, landmarks: np.ndarray) -> float:
        """检测吃饭喝水行为"""
        # 安全检查landmarks是否有效
        try:
            if not isinstance(landmarks, np.ndarray) and not hasattr(landmarks, '__len__'):
                return 0.0
            
            # 检查关键点是否足够
            if isinstance(landmarks, np.ndarray) and landmarks.shape[0] < 17:
                return 0.0
            elif hasattr(landmarks, '__len__') and len(landmarks) < 17:
                return 0.0
        except:
            return 0.0
        
        # 简化的饮食检测：手部靠近嘴巴
        try:
            # 获取关键点
            left_hand = landmarks[15]  # 左手腕
            right_hand = landmarks[16]  # 右手腕
            nose = landmarks[0]  # 鼻子
            
            # 计算手部到鼻子的距离（简化计算）
            try:
                left_to_nose = math.sqrt((left_hand[0] - nose[0])**2 + (left_hand[1] - nose[1])** 2)
                right_to_nose = math.sqrt((right_hand[0] - nose[0])** 2 + (right_hand[1] - nose[1])** 2)
            except:
                return 0.0
            
            score = 0.0
            
            # 手部靠近嘴巴
            if left_to_nose < 0.15 or right_to_nose < 0.15:
                score += 0.6
            
            # 使用历史数据检测手部运动（如果有足够历史）
            if len(self.landmark_history) > 5:
                try:
                    # 简单检测手部是否有上下运动
                    hand_movement = False
                    for i in range(1, min(5, len(self.landmark_history))):
                        prev = self.landmark_history[-i-1]
                        curr = self.landmark_history[-i]
                        
                        # 检查手部是否向上移动
                        if (hasattr(prev, '__getitem__') and hasattr(curr, '__getitem__') and
                            len(prev) > 16 and len(curr) > 16):
                            prev_left_y = prev[15][1] if hasattr(prev[15], '__getitem__') else 0
                            curr_left_y = curr[15][1] if hasattr(curr[15], '__getitem__') else 0
                            prev_right_y = prev[16][1] if hasattr(prev[16], '__getitem__') else 0
                            curr_right_y = curr[16][1] if hasattr(curr[16], '__getitem__') else 0
                            
                            if (curr_left_y < prev_left_y * 0.95) or (curr_right_y < prev_right_y * 0.95):
                                hand_movement = True
                                break
                    
                    if hand_movement:
                        score += 0.4
                except:
                    pass
            
            return min(0.95, score)
        except:
            return 0.0
        
        return min(0.95, score)
    
    def _detect_stretching(self, landmarks: np.ndarray) -> float:
        """检测伸展行为"""
        # 安全检查landmarks是否有效且有足够的数据
        try:
            if isinstance(landmarks, np.ndarray) and landmarks.shape[0] < 17:
                return 0.0
            elif hasattr(landmarks, '__len__') and len(landmarks) < 17:
                return 0.0
        except:
            return 0.0
        
        # 获取关键点
        left_shoulder = landmarks[11]
        right_shoulder = landmarks[12]
        left_elbow = landmarks[13]
        right_elbow = landmarks[14]
        left_wrist = landmarks[15]
        right_wrist = landmarks[16]
        
        # 计算手臂伸展角度
        left_arm_angle = self._calculate_angle(left_shoulder, left_elbow, left_wrist)
        right_arm_angle = self._calculate_angle(right_shoulder, right_elbow, right_wrist)
        
        # 计算手臂举起高度
        left_arm_raised = 1.0 if left_wrist[1] < left_shoulder[1] else 0.0
        right_arm_raised = 1.0 if right_wrist[1] < right_shoulder[1] else 0.0
        
        score = 0.0
        
        # 手臂伸展（接近180度）
        if left_arm_angle > 160:
            score += 0.4
        elif left_arm_angle > 140:
            score += 0.2
            
        if right_arm_angle > 160:
            score += 0.4
        elif right_arm_angle > 140:
            score += 0.2
        
        # 手臂举起
        score += (left_arm_raised + right_arm_raised) * 0.2
        
        # 检查是否有大幅度身体动作
        if len(self.landmark_history) >= 5:
            body_movement = self._calculate_overall_movement()
            if body_movement > self.movement_threshold * 1.5:
                score += 0.2
        
        return min(0.95, score)
    
    def _detect_standing(self, landmarks, pose_result: Dict) -> float:
        """检测站立行为"""
        if pose_result.get('pose') == 'standing':
            # 检查身体是否挺直
            body_straightness = self._calculate_body_straightness(landmarks)
            return min(0.9, 0.5 + body_straightness * 0.4)
        
        return 0.0
    
    def _detect_sitting(self, landmarks, pose_result: Dict) -> float:
        """检测坐着行为"""
        if pose_result.get('pose') == 'sitting':
            # 检查坐姿是否端正
            sitting_posture = self._calculate_sitting_posture(landmarks)
            return min(0.9, 0.5 + sitting_posture * 0.4)
        
        return 0.0
    
    def _calculate_head_angle(self, landmarks) -> float:
        """计算头部角度"""
        try:
            if landmarks is None:
                return 0.0
            
            # 处理MediaPipe的landmarks对象
            if hasattr(landmarks, 'landmark'):
                # 获取关键点
                nose = landmarks.landmark[0]
                left_eye = landmarks.landmark[2]
                right_eye = landmarks.landmark[5]
                
                # 计算眼睛连线与水平线的夹角
                eye_vector = [right_eye.x - left_eye.x, right_eye.y - left_eye.y]
                angle = math.degrees(math.atan2(eye_vector[1], eye_vector[0]))
                return angle
            else:
                return 0.0
        except Exception as e:
            return 0.0
    
    def _calculate_body_angle(self, landmarks) -> float:
        """计算身体角度"""
        try:
            if landmarks is None:
                return 0.0
            
            # 处理MediaPipe的landmarks对象
            if hasattr(landmarks, 'landmark'):
                # 获取关键点
                left_shoulder = landmarks.landmark[11]
                right_shoulder = landmarks.landmark[12]
                left_hip = landmarks.landmark[23]
                right_hip = landmarks.landmark[24]
                
                # 计算肩膀和臀部的中心点
                shoulder_center = [(left_shoulder.x + right_shoulder.x)/2, 
                                 (left_shoulder.y + right_shoulder.y)/2]
                hip_center = [(left_hip.x + right_hip.x)/2, 
                             (left_hip.y + right_hip.y)/2]
                body_vector = [hip_center[0] - shoulder_center[0], 
                             hip_center[1] - shoulder_center[1]]
                
                angle = math.degrees(math.atan2(body_vector[0], body_vector[1]))
                return angle
            else:
                return 0.0
        except Exception as e:
            return 0.0
    
    def _get_landmark_coords(self, landmarks, index):
        """获取指定索引的关键点坐标"""
        try:
            if hasattr(landmarks, 'landmark'):
                if len(landmarks.landmark) > index:
                    landmark = landmarks.landmark[index]
                    return (landmark.x, landmark.y, landmark.z)
            elif hasattr(landmarks, '__len__') and len(landmarks) > index:
                landmark = landmarks[index]
                if hasattr(landmark, 'x'):
                    return (landmark.x, landmark.y, landmark.z)
                else:
                    return landmark
            return None
        except:
            return None
    
    def _detect_eye_closed(self, landmarks) -> bool:
        """检测眼睛是否闭合 - 简化版本"""
        try:
            if landmarks is None or not hasattr(landmarks, 'landmark'):
                return False
            
            # 检查关键点数量
            if len(landmarks.landmark) < 33:
                return False
            
            # 使用简单的眼睛关键点检测
            # 左眼关键点
            left_eye_top = landmarks.landmark[159]    # 左眼上
            left_eye_bottom = landmarks.landmark[145] # 左眼下
            # 右眼关键点  
            right_eye_top = landmarks.landmark[386]   # 右眼上
            right_eye_bottom = landmarks.landmark[374] # 右眼下
            
            # 计算眼睛的垂直距离
            left_eye_height = abs(left_eye_top.y - left_eye_bottom.y)
            right_eye_height = abs(right_eye_top.y - right_eye_bottom.y)
            
            # 平均眼睛高度
            avg_eye_height = (left_eye_height + right_eye_height) / 2.0
            
            # 阈值，低于此值认为眼睛闭合
            height_threshold = 0.01
            
            return avg_eye_height < height_threshold
            
        except Exception as e:
            return False
    
    def _calculate_leg_movement(self) -> float:
        """计算腿部运动强度"""
        # 为了解决len()错误，简化实现，直接返回默认值
        try:
            if len(self.landmark_history) < 5:
                return 0.0
        except:
            pass
            
        return 0.0
    
    def _calculate_overall_movement(self) -> float:
        """计算整体运动强度"""
        # 安全检查历史记录
        try:
            if len(self.landmark_history) < 5:
                return 0.0
        except:
            return 0.0
        
        movements = []
        
        for i in range(len(self.landmark_history) - 1):
            try:
                prev_landmarks = self.landmark_history[i]
                curr_landmarks = self.landmark_history[i + 1]
                
                # 处理MediaPipe的landmarks对象
                if (hasattr(prev_landmarks, 'landmark') and hasattr(curr_landmarks, 'landmark') and
                    len(prev_landmarks.landmark) >= 33 and len(curr_landmarks.landmark) >= 33):
                    
                    # 计算所有关键点的平均运动
                    total_movement = 0
                    valid_points = 0
                    
                    for j in range(min(len(prev_landmarks.landmark), len(curr_landmarks.landmark))):
                        try:
                            prev_point = prev_landmarks.landmark[j]
                            curr_point = curr_landmarks.landmark[j]
                            
                            # 计算两点之间的距离
                            movement = math.sqrt(
                                (curr_point.x - prev_point.x)**2 + 
                                (curr_point.y - prev_point.y)**2 + 
                                (curr_point.z - prev_point.z)**2
                            )
                            total_movement += movement
                            valid_points += 1
                        except:
                            pass
                    
                    if valid_points > 0:
                        movements.append(total_movement / valid_points)
            except:
                pass
        
        return np.mean(movements) if movements else 0.0
    
    def _calculate_head_turn(self) -> float:
        """计算头部转动角度"""
        # 安全检查landmark_history
        try:
            if len(self.landmark_history) < 2:
                return 0.0
        except:
            return 0.0
        
        # 比较当前和之前的头部角度
        current_angle = self._calculate_head_angle(self.landmark_history[-1])
        prev_angle = self._calculate_head_angle(self.landmark_history[-2])
        
        return current_angle - prev_angle
    
    def _calculate_body_turn(self) -> float:
        """计算身体转动角度"""
        # 安全检查landmark_history
        try:
            if len(self.landmark_history) < 2:
                return 0.0
        except:
            return 0.0
        
        # 比较当前和之前的身体角度
        current_angle = self._calculate_body_angle(self.landmark_history[-1])
        prev_angle = self._calculate_body_angle(self.landmark_history[-2])
        
        return current_angle - prev_angle
    
    def _calculate_head_turn_frequency(self) -> float:
        """计算头部转动频率"""
        # 安全检查landmark_history
        try:
            if len(self.landmark_history) < 5:
                return 0.0
        except:
            return 0.0
        
        # 计算最近10帧的头部转动次数
        turn_count = 0
        for i in range(len(self.landmark_history) - 1):
            head_turn = abs(self._calculate_head_turn())
            if head_turn > 10:  # 转动超过10度算一次
                turn_count += 1
        
        return turn_count / len(self.landmark_history)
    
    def _calculate_hand_activity(self) -> float:
        """计算手部活动强度"""
        # 安全检查landmark_history
        try:
            if len(self.landmark_history) < 5:
                return 0.0
        except:
            return 0.0
        
        # 使用手腕关键点计算手部运动
        hand_movements = []
        
        for i in range(len(self.landmark_history) - 1):
            try:
                prev_landmarks = self.landmark_history[i]
                curr_landmarks = self.landmark_history[i + 1]
                
                # 处理MediaPipe的landmarks对象
                if (hasattr(prev_landmarks, 'landmark') and hasattr(curr_landmarks, 'landmark') and
                    len(prev_landmarks.landmark) >= 33 and len(curr_landmarks.landmark) >= 33):
                    
                    # 左手腕和右手腕
                    left_wrist_prev = prev_landmarks.landmark[15]
                    left_wrist_curr = curr_landmarks.landmark[15]
                    right_wrist_prev = prev_landmarks.landmark[16]
                    right_wrist_curr = curr_landmarks.landmark[16]
                    
                    # 计算手腕运动距离
                    left_movement = math.sqrt(
                        (left_wrist_curr.x - left_wrist_prev.x)**2 + 
                        (left_wrist_curr.y - left_wrist_prev.y)**2 + 
                        (left_wrist_curr.z - left_wrist_prev.z)**2
                    )
                    right_movement = math.sqrt(
                        (right_wrist_curr.x - right_wrist_prev.x)**2 + 
                        (right_wrist_curr.y - right_wrist_prev.y)**2 + 
                        (right_wrist_curr.z - right_wrist_prev.z)**2
                    )
                    
                    hand_movements.append((left_movement + right_movement) / 2)
            except:
                pass
        
        return np.mean(hand_movements) if hand_movements else 0.0
    
    def _calculate_body_lean(self, landmarks) -> float:
        """计算身体前倾角度"""
        try:
            if landmarks is None:
                return 0.0
            
            # 处理MediaPipe的landmarks对象
            if hasattr(landmarks, 'landmark'):
                # 获取关键点
                left_shoulder = landmarks.landmark[11]
                right_shoulder = landmarks.landmark[12]
                left_hip = landmarks.landmark[23]
                right_hip = landmarks.landmark[24]
                
                # 计算肩膀和臀部的中心点
                shoulder_center = [(left_shoulder.x + right_shoulder.x)/2, 
                                 (left_shoulder.y + right_shoulder.y)/2]
                hip_center = [(left_hip.x + right_hip.x)/2, 
                             (left_hip.y + right_hip.y)/2]
                
                # 计算身体向量
                body_vector = [hip_center[0] - shoulder_center[0], 
                             hip_center[1] - shoulder_center[1]]
                
                # 计算与垂直线的夹角
                angle = math.degrees(math.atan2(body_vector[0], body_vector[1]))
                return abs(angle)
            else:
                return 0.0
        except:
            return 0.0
    
    def _calculate_hand_position(self, landmarks) -> float:
        """计算手部位置分数"""
        try:
            if landmarks is None:
                return 0.0
            
            # 处理MediaPipe的landmarks对象
            if hasattr(landmarks, 'landmark'):
                # 获取关键点
                left_wrist = landmarks.landmark[15]
                right_wrist = landmarks.landmark[16]
                left_shoulder = landmarks.landmark[11]
                right_shoulder = landmarks.landmark[12]
                
                shoulder_center = [(left_shoulder.x + right_shoulder.x)/2, 
                                 (left_shoulder.y + right_shoulder.y)/2]
                wrist_center = [(left_wrist.x + right_wrist.x)/2, 
                              (left_wrist.y + right_wrist.y)/2]
                
                # 计算手部相对于肩膀的位置
                hand_offset = wrist_center[1] - shoulder_center[1]  # Y轴偏移
                
                # 手部在肩膀下方且距离适中
                if 0 < hand_offset < 0.2:
                    return 1.0
                elif 0 < hand_offset < 0.3:
                    return 0.7
                else:
                    return 0.3
            else:
                return 0.0
        except:
            return 0.0
    
    def _calculate_hand_stability(self) -> float:
        """计算手部稳定性"""
        try:
            if len(self.landmark_history) < 5:
                return 0.0
        except:
            return 0.0
        
        # 计算手部位置的变化程度
        hand_movements = []
        for i in range(len(self.landmark_history) - 1):
            try:
                prev_landmarks = self.landmark_history[i]
                curr_landmarks = self.landmark_history[i + 1]
                
                if len(prev_landmarks) >= 33 and len(curr_landmarks) >= 33:
                    # 计算手腕位置变化
                    left_wrist_prev = prev_landmarks[15]
                    left_wrist_curr = curr_landmarks[15]
                    right_wrist_prev = prev_landmarks[16]
                    right_wrist_curr = curr_landmarks[16]
                    
                    left_movement = np.linalg.norm(left_wrist_curr - left_wrist_prev)
                    right_movement = np.linalg.norm(right_wrist_curr - right_wrist_prev)
                    
                    hand_movements.append((left_movement + right_movement) / 2)
            except:
                pass
        
        if not hand_movements:
            return 0.0
        
        # 稳定性是运动幅度的倒数
        avg_movement = np.mean(hand_movements)
        stability = 1.0 / (1.0 + avg_movement * 10)  # 归一化到0-1
        
        return stability
    
    def _calculate_head_orientation_score(self, landmarks) -> float:
        """计算头部朝向分数"""
        try:
            if landmarks is None:
                return 0.0
            
            # 处理MediaPipe的landmarks对象
            if hasattr(landmarks, 'landmark'):
                # 获取关键点
                nose = landmarks.landmark[0]
                left_eye = landmarks.landmark[2]
                right_eye = landmarks.landmark[5]
                
                # 计算眼睛中心点
                eye_center = [(left_eye.x + right_eye.x)/2, 
                             (left_eye.y + right_eye.y)/2]
                
                # 计算头部朝向向量
                head_vector = [nose.x - eye_center[0], nose.y - eye_center[1]]
                
                # 计算朝向分数（简化实现）
                orientation_score = 1.0 - abs(head_vector[0])  # X轴偏移越小，朝向越正
                orientation_score = max(0.0, min(1.0, orientation_score))
                
                return orientation_score
            else:
                return 0.0
        except:
            return 0.0
    
    def _calculate_body_straightness(self, landmarks) -> float:
        """计算身体挺直程度"""
        try:
            if landmarks is None:
                return 0.0
            
            # 处理MediaPipe的landmarks对象
            if hasattr(landmarks, 'landmark'):
                # 获取关键点
                left_shoulder = landmarks.landmark[11]
                right_shoulder = landmarks.landmark[12]
                left_hip = landmarks.landmark[23]
                right_hip = landmarks.landmark[24]
                left_knee = landmarks.landmark[25]
                right_knee = landmarks.landmark[26]
                
                # 计算身体各部分的中心点
                shoulder_center = [(left_shoulder.x + right_shoulder.x)/2, 
                                 (left_shoulder.y + right_shoulder.y)/2]
                hip_center = [(left_hip.x + right_hip.x)/2, 
                             (left_hip.y + right_hip.y)/2]
                knee_center = [(left_knee.x + right_knee.x)/2, 
                              (left_knee.y + right_knee.y)/2]
                
                # 计算身体各段的角度
                upper_body_angle = self._calculate_angle(shoulder_center, hip_center)
                lower_body_angle = self._calculate_angle(hip_center, knee_center)
                
                # 身体越挺直，角度越接近90度
                straightness = 1.0 - abs(90 - upper_body_angle) / 90.0
                straightness += 1.0 - abs(90 - lower_body_angle) / 90.0
                
                return straightness / 2.0
            else:
                return 0.0
        except:
            return 0.0
    
    def _calculate_sitting_posture(self, landmarks) -> float:
        """计算坐姿端正程度"""
        try:
            if landmarks is None:
                return 0.0
            
            # 处理MediaPipe的landmarks对象
            if hasattr(landmarks, 'landmark'):
                # 检查背部是否挺直
                back_straightness = self._calculate_body_straightness(landmarks)
                
                # 检查腿部角度（坐着时膝盖应该弯曲）
                left_knee = landmarks.landmark[25]
                right_knee = landmarks.landmark[26]
                left_hip = landmarks.landmark[23]
                right_hip = landmarks.landmark[24]
                left_ankle = landmarks.landmark[27]
                right_ankle = landmarks.landmark[28]
                
                # 计算膝盖弯曲角度
                left_knee_angle = self._calculate_angle(
                    [left_hip.x, left_hip.y], 
                    [left_knee.x, left_knee.y], 
                    [left_ankle.x, left_ankle.y]
                )
                right_knee_angle = self._calculate_angle(
                    [right_hip.x, right_hip.y], 
                    [right_knee.x, right_knee.y], 
                    [right_ankle.x, right_ankle.y]
                )
                
                # 坐着时膝盖角度应该在90-120度之间
                knee_score = 0.0
                if 90 <= left_knee_angle <= 120:
                    knee_score += 0.5
                if 90 <= right_knee_angle <= 120:
                    knee_score += 0.5
                
                return (back_straightness + knee_score) / 2.0
            else:
                return 0.0
        except:
            return 0.0
    
    def _calculate_angle(self, p1, p2, p3=None) -> float:
        """计算角度"""
        if p3 is None:
            # 计算两点与水平线的夹角
            vector = p2 - p1
            angle = math.degrees(math.atan2(vector[1], vector[0]))
            return abs(angle)
        else:
            # 计算三点形成的角度
            v1 = p1 - p2
            v2 = p3 - p2
            
            cos_angle = np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2))
            cos_angle = np.clip(cos_angle, -1.0, 1.0)
            angle = math.degrees(math.acos(cos_angle))
            
            return angle
    
    def _get_behavior_chinese_name(self, behavior: str) -> str:
        """获取行为的中文名称"""
        behavior_names = {
            'sleeping': '睡觉',
            'walking': '走路',
            'turning': '转身',
            'chatting': '聊天',
            'eating': '吃东西',
            'raising_left': '左手举手',
            'raising_right': '右手举手',
            'raising_both': '双手举手',
            'extend_left': '左手伸直',
            'extend_right': '右手伸直',
            'extend_both': '双手伸直',
            'extend_both_horizontal': '平伸双手',
            'jumping_knees_up': '跳跃/双膝上抬',
            'working': '工作',
            'standing': '站立',
            'sitting': '坐着',
            'unknown': '未知'
        }
        return behavior_names.get(behavior, '未知')
    
    def _get_unknown_behavior(self) -> Dict:
        """获取未知行为结果"""
        return {
            'behavior': 'unknown',
            'confidence': 0.0,
            'duration': 0.0,
            'chinese_name': '未知',
            'all_behaviors': {}
        }
    
    def get_behavior_summary(self) -> Dict:
        """获取行为摘要"""
        return {
            'current_behavior': self.current_behavior,
            'chinese_name': self._get_behavior_chinese_name(self.current_behavior),
            'confidence': self.behavior_confidence,
            'duration': self.behavior_duration,
            'history_size': len(self.pose_history)
        }
